package net.esj.basic.plugins.spring.factory.xml.parser;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import net.esj.basic.core.engine.tools.NetworkManagement;
import net.esj.basic.dao.hibernate.HibernateSessionLocale;
import net.esj.basic.plugins.spring.factory.xml.DefaultMelonIocUtils;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class SupportBeanDefinitionParser implements BeanDefinitionParser {

	@Override
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		
//		if(!checkCanUse()){
//			parserContext.getReaderContext().error("小子，想用盗版?", null);
//			return null;
//		}
		Map<String,String> refs = new HashMap<String, String>();
//		String hibernate = element.getAttribute("hibernate");
//		if (StringUtils.hasText(hibernate)
//				&& "true".equalsIgnoreCase(hibernate)) {
//			registerHibernateSourceLocale(element, parserContext);
//			regisiterHibernateSessionLocale(element, parserContext, element.getAttribute("hibernateType"));
//		}
//		
//		regisiterJdbcSourceLocale(element, parserContext);
//		regisiterDaoProxy(element, parserContext);
		regisiterDao(element, parserContext);
		
		String translator = regisiterTranslator(element, parserContext);
		if(StringUtils.hasText(translator)){
			refs.put("translator", translator);
		}
		
		String validator = regisiterValidator(element, parserContext);
		if(StringUtils.hasText(validator)){
			refs.put("validator", validator);
		}
		
		String service = regisiterService(element, parserContext);
		if(StringUtils.hasText(service)){
			refs.put("service", service);
		}
		
		String pwdEncryptor = regisiterPwdEncryptor(element, parserContext);
		if(StringUtils.hasText(pwdEncryptor)){
			refs.put("pwdEncryptor", pwdEncryptor);
		}
		
		String viewer = regisiterViewer(element,parserContext);
		if(StringUtils.hasText(viewer)){
			refs.put("viewer", viewer);
		}
		
		
		String mp =  regisiterMessageProvider(element, parserContext);
		if(StringUtils.hasText(mp)){
			refs.put("messageProvider", mp);
		}
		
		regisiterSupporter(parserContext, refs);
		return null;
	}

	
	private String regisiterTranslator(Element element, ParserContext parserContext){
		NodeList nodes = element.getElementsByTagName("melon:translator");
		String classname = DefaultMelonIocUtils.MELON_TRANSLATOR_BEAN_NAME;
		String classref = null;
		if(nodes.getLength()>0){
			Element targetElement = null;
			for(int i=0;i<nodes.getLength();i++){//只取最后一个
				Node node = nodes.item(i);
				targetElement = (Element) node;
			}
			classref = targetElement.getAttribute("class");
			if(!StringUtils.hasText(classref)){
				classref = DefaultMelonIocUtils.DEFAULT_TRANSLATOR.getName();
			}
		}
		if(StringUtils.hasText(classref)){
			BeanDefinitionBuilder builder = BeanDefinitionBuilder
				.genericBeanDefinition(classref);
			parserContext.registerBeanComponent(
					new BeanComponentDefinition(builder.getBeanDefinition(),classname));
			return classname;
		}
		return null;
	}
	
	private String regisiterValidator(Element element, ParserContext parserContext){
		NodeList nodes = element.getElementsByTagName("melon:validator");
		String classname = DefaultMelonIocUtils.MELON_VALIDATOR_BEAN_NAME;
		String classref = null;
		if(nodes.getLength()>0){
			Element targetElement = null;
			for(int i=0;i<nodes.getLength();i++){//只取最后一个
				Node node = nodes.item(i);
				targetElement = (Element) node;
			}
			classref = targetElement.getAttribute("class");
			if(!StringUtils.hasText(classref)){
				classref = DefaultMelonIocUtils.DEFAULT_VALIDATOR.getName();
			}
		}
		if(StringUtils.hasText(classref)){
			BeanDefinitionBuilder builder = BeanDefinitionBuilder
				.genericBeanDefinition(classref);
			parserContext.registerBeanComponent(
					new BeanComponentDefinition(builder.getBeanDefinition(),classname));
			return classname;
		}
		return null;
	}
	
	private String regisiterService(Element element, ParserContext parserContext){
		NodeList nodes = element.getElementsByTagName("melon:service");
		String classname = DefaultMelonIocUtils.MELON_DEFAULT_SERVICE_BEAN_NAME;
		String classref = null;
		String translator = null;
		String validator = null;
		if(nodes.getLength()>0){
			Element targetElement = null;
			for(int i=0;i<nodes.getLength();i++){//只取最后一个
				Node node = nodes.item(i);
				targetElement = (Element) node;
			}
			classref = targetElement.getAttribute("class");
			if(!StringUtils.hasText(classref)){
				classref = DefaultMelonIocUtils.DEFAULT_BASIC_SERVICE.getName();
			}
		}else{
			return null;
		}
		if(StringUtils.hasText(classref)){
			BeanDefinitionBuilder builder = BeanDefinitionBuilder
				.genericBeanDefinition(classref);
			
			parserContext.registerBeanComponent(
					new BeanComponentDefinition(builder.getBeanDefinition(),classname));
		}else{
			return null;
		}
		return classname;
	}
	
	private String regisiterPwdEncryptor(Element element, ParserContext parserContext){
		NodeList nodes = element.getElementsByTagName("melon:pwdencryptor");
		String classname = DefaultMelonIocUtils.MELON_DEFAULT_PWDENCRYPTOR_BEAN_NAME;
		String classref = null;
		String secretKey = null;
		if(nodes.getLength()>0){
			Element targetElement = null;
			for(int i=0;i<nodes.getLength();i++){//只取最后一个
				Node node = nodes.item(i);
				targetElement = (Element) node;
			}
			classref = targetElement.getAttribute("class");
			if(!StringUtils.hasText(classref)){
				classref = DefaultMelonIocUtils.DEFAULT_PWDENCRYPTOR.getName();
			}
			
			secretKey = targetElement.getAttribute("secretKey");
			
		}
		if(StringUtils.hasText(classref)){
			BeanDefinitionBuilder builder = BeanDefinitionBuilder
				.genericBeanDefinition(classref);
			
			if(StringUtils.hasText(secretKey)){
				builder.addPropertyValue("secretKey", secretKey);
			}
			
			parserContext.registerBeanComponent(
					new BeanComponentDefinition(builder.getBeanDefinition(),classname));
			return classname;
		}
		
		return null;
	}
	
	private String regisiterDao(Element element, ParserContext parserContext){
		NodeList nodes = element.getElementsByTagName("melon:dao");
		if(nodes.getLength()<=0){
			return "";
		}
		Element daoElement = null;
		for(int i=0;i<nodes.getLength();i++){//只取最后一个
			Node node = nodes.item(i);
			daoElement = (Element) node;
		}
		
		
		List daoSources = new ArrayList();
		NodeList sourceNodes =  daoElement.getElementsByTagName("melon:source");
		
		if(sourceNodes.getLength()>0){
			for(int i=0;i<sourceNodes.getLength();i++){//数据源
				Node node = sourceNodes.item(i);
				Element srcElement = (Element) node;
				String id = srcElement.getAttribute("id");
				DaoSource source = DefaultMelonIocUtils.DEFAULT_DAO_SOURCES.get(id);
				if(source!=null){
					try {
						source = (DaoSource) source.clone();
					} catch (CloneNotSupportedException e) {
						source = new DaoSource(id);
					}
				}else{
					source = new DaoSource(id);
				}
				String clazz = srcElement.getAttribute("class");
				if(StringUtils.hasText(clazz)){
					source.setClazz(clazz);
				}
				String src = srcElement.getAttribute("source");
				if(StringUtils.hasText(src)){
					source.setSource(src);
				}
				
				String srcref = srcElement.getAttribute("source-ref");
				if(StringUtils.hasText(srcref)){
					source.setSourceRef(srcref);
				}
				String dao = srcElement.getAttribute("dao");
				if(StringUtils.hasText(dao)){
					source.setDao(dao);
				}
				String daoref = srcElement.getAttribute("dao-ref");
				if(StringUtils.hasText(daoref)){
					source.setDaoRef(daoref);
				}
				regisiterSource(parserContext, source);
				if(StringUtils.hasText(source.getDaoRef())){
					daoSources.add(source.getDaoRef());
				}else if(StringUtils.hasText(source.getDao())){
					daoSources.add(source.getDao());
				}
			}
		}else{//如果没有配置 则用默认值
			List<DaoSource> list = new ArrayList<DaoSource>(DefaultMelonIocUtils.DEFAULT_DAO_SOURCES.values());
			for(DaoSource source : list){
				regisiterSource(parserContext, source);
				if(StringUtils.hasText(source.getDaoRef())){
					daoSources.add(source.getDaoRef());
				}else if(StringUtils.hasText(source.getDao())){
					daoSources.add(source.getDao());
				}
			}
		}
		BeanDefinitionBuilder builder = BeanDefinitionBuilder
		.genericBeanDefinition(DefaultMelonIocUtils.DEFAULT_DAO_PROXY);
		//builder.addPropertyReference("persistentClass", persistentClass);
		builder.addPropertyValue("daoSources", daoSources);
		parserContext.registerBeanComponent(new BeanComponentDefinition(builder
				.getBeanDefinition(), DefaultMelonIocUtils.DEFAULT_DAO_PROXY.getName()));
		return DefaultMelonIocUtils.DEFAULT_DAO_PROXY.getName();
	}
	
	/**
	 * 注册melon:source
	 * @param parserContext
	 * @param source
	 */
	private void regisiterSource(ParserContext parserContext,DaoSource source){
		
		if(StringUtils.hasText(source.getSource()) && !StringUtils.hasText(source.getSourceRef())){ //ref不存在则创建 否则以REF为准
			BeanDefinitionBuilder srcbuilder = BeanDefinitionBuilder
			.genericBeanDefinition(source.getSource());
			
			try {
				Class clazz = Class.forName(source.getSource());
				if(HibernateSessionLocale.class.isAssignableFrom(clazz)){
					srcbuilder.addPropertyReference("sessionFactory", "sessionFactory");
				}
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
			
			
			parserContext.registerBeanComponent(
					new BeanComponentDefinition(srcbuilder.getBeanDefinition(),source.getSource()));
		}
		
		BeanDefinitionBuilder builder = BeanDefinitionBuilder
		.genericBeanDefinition(source.getClazz());
		if(StringUtils.hasText(source.getSourceRef())){
			builder.addPropertyReference("source", source.getSourceRef());
		}else if(StringUtils.hasText(source.getSource())){
			builder.addPropertyReference("source", source.getSource());
		}
		String sourcelocaleBeanname = source.getId()+"SourceLocale";
		parserContext.registerBeanComponent(
				new BeanComponentDefinition(builder.getBeanDefinition(),sourcelocaleBeanname));
		
		if(StringUtils.hasText(source.getDao()) && !StringUtils.hasText(source.getDaoRef())){ //ref不存在则创建 否则以REF为准
			BeanDefinitionBuilder daobuilder = BeanDefinitionBuilder
			.genericBeanDefinition(source.getDao());
			daobuilder.addPropertyReference("sourceLocale", sourcelocaleBeanname);
			parserContext.registerBeanComponent(
					new BeanComponentDefinition(daobuilder.getBeanDefinition(),source.getDao()));
		}
	}
	
	private void regisiterSupporter(ParserContext parserContext,Map<String,String> refs){
		BeanDefinitionBuilder builder = BeanDefinitionBuilder
		.genericBeanDefinition(DefaultMelonIocUtils.DEFAULT_MELON_SUPPORT);
		for(Map.Entry<String, String> entry : refs.entrySet()){
			builder.addPropertyReference(entry.getKey(), entry.getValue());
		}
		parserContext.registerBeanComponent(
				new BeanComponentDefinition(builder.getBeanDefinition(),DefaultMelonIocUtils.DEFAULT_MELON_SUPPORT.getName()));
	}
	
	private String regisiterViewer(Element element, ParserContext parserContext){
		
		Map<String,String> viewerrefs = new HashMap<String, String>();
		
		NodeList nodes = element.getElementsByTagName("melon:viewer");
		if(nodes.getLength()<=0){
			return null;
		}
		Element viewerElement = null;
		for(int i=0;i<nodes.getLength();i++){//只取最后一个
			Node node = nodes.item(i);
			viewerElement = (Element) node;
		}
	
		NodeList agentNodes = viewerElement.getElementsByTagName("melon:agentContext");
		Element agentElement = null;
		for(int i=0;i<agentNodes.getLength();i++){//只取最后一个
			Node node = agentNodes.item(i);
			agentElement = (Element) node;
		}
		String agentClass = null;
		if(agentElement!=null){
			agentClass = agentElement.getAttribute("class");
		}
		if(!StringUtils.hasText(agentClass)){
			agentClass = DefaultMelonIocUtils.DEFAULT_AGENT_CONTEXT.getName();
		}
		BeanDefinitionBuilder builder = BeanDefinitionBuilder
		.genericBeanDefinition(agentClass);
		parserContext.registerBeanComponent(
				new BeanComponentDefinition(builder.getBeanDefinition(),agentClass));
		viewerrefs.put("agentContext", agentClass);
		/* **以上创建agentContext**/
		
		NodeList jsonNodes = viewerElement.getElementsByTagName("melon:writer");
		Element jsonElement = null;
		for(int i=0;i<jsonNodes.getLength();i++){//只取最后一个
			Node node = jsonNodes.item(i);
			jsonElement = (Element) node;
		}
		String jsonClass = null;
		if(jsonElement!=null){
			jsonClass = jsonElement.getAttribute("class");
		}
		if(!StringUtils.hasText(jsonClass)){
			jsonClass = DefaultMelonIocUtils.DEFAULT_JSON_WRITER.getName();
		}
		BeanDefinitionBuilder jsonbuilder = BeanDefinitionBuilder
		.genericBeanDefinition(jsonClass);
		parserContext.registerBeanComponent(
				new BeanComponentDefinition(jsonbuilder.getBeanDefinition(),jsonClass));
		viewerrefs.put("writer", jsonClass);
		/* **以上创建writer**/
		
		BeanDefinitionBuilder viewerbuilder = BeanDefinitionBuilder
		.genericBeanDefinition(DefaultMelonIocUtils.DEFAULT_VIEWER);
		for(Map.Entry<String, String> entry : viewerrefs.entrySet()){
			viewerbuilder.addPropertyReference(entry.getKey(), entry.getValue());
		}
		parserContext.registerBeanComponent(
				new BeanComponentDefinition(viewerbuilder.getBeanDefinition(),DefaultMelonIocUtils.DEFAULT_VIEWER.getName()));
		return DefaultMelonIocUtils.DEFAULT_VIEWER.getName();
	}
	
	private String regisiterMessageProvider(Element element, ParserContext parserContext){
		NodeList nodes = element.getElementsByTagName("melon:message");
		if(nodes.getLength()<=0){
			return null;
		}
		Element msgElement = null;
		for(int i=0;i<nodes.getLength();i++){//只取最后一个
			Node node = nodes.item(i);
			msgElement = (Element) node;
		}
		
		String clazz = msgElement.getAttribute("class");
		if(!StringUtils.hasText(clazz)){
			clazz = DefaultMelonIocUtils.DEFAULT_MESSAGE_PROVIDER.getName();
		}
	
		BeanDefinitionBuilder builder = BeanDefinitionBuilder
		.genericBeanDefinition(clazz);
		parserContext.registerBeanComponent(
				new BeanComponentDefinition(builder.getBeanDefinition(),clazz));
		return clazz;
	}
	
	private boolean checkCanUse(){
		return !NetworkManagement.isNetWorkLinked();
	}
	
	public static class DaoSource implements Cloneable{
		private String id;
		private String clazz;
		private String source;
		private String sourceRef;
		private String dao;
		private String daoRef;
		
		
		
		public DaoSource(String id) {
			super();
			this.id = id;
		}
		public DaoSource() {
			super();
		}
		
		public String getId() {
			return id;
		}
		public void setId(String id) {
			this.id = id;
		}
		public String getClazz() {
			return clazz;
		}
		public void setClazz(String clazz) {
			this.clazz = clazz;
		}
		public String getSource() {
			return source;
		}
		public void setSource(String source) {
			this.source = source;
		}
		public String getSourceRef() {
			return sourceRef;
		}
		public void setSourceRef(String sourceRef) {
			this.sourceRef = sourceRef;
		}
		public String getDao() {
			return dao;
		}
		public void setDao(String dao) {
			this.dao = dao;
		}
		public String getDaoRef() {
			return daoRef;
		}
		public void setDaoRef(String daoRef) {
			this.daoRef = daoRef;
		}
		@Override
		public Object clone() throws CloneNotSupportedException {
			return super.clone();
		}
		
	}
	
	
	/**
	 * 
	 * @param element
	 * @param parserContext
	 */
	@Deprecated
	private void registerHibernateSourceLocale(Element element,
			ParserContext parserContext) {
		
		String hib = element.getAttribute("hibernate");
		
		if(!StringUtils.hasText(hib)){
			return;
		}
		
//		String
		
		if (!parserContext
				.getRegistry()
				.containsBeanDefinition(
						HibernateSourceLocaleBeanDefinitionParser.DEFAULT_HIBERNATE_SESSION_LOCAL)) {// 創建sourcelocale
			BeanDefinitionBuilder sessionbuilder = BeanDefinitionBuilder
					.genericBeanDefinition(HibernateSourceLocaleBeanDefinitionParser.DEFAULT_HIBERNATE_SESSION_LOCAL);
			sessionbuilder.addPropertyReference("sessionFactory",
					"sessionFactory");
			// String generatedName =
			// parserContext.getReaderContext().generateBeanName(sessionbuilder.getRawBeanDefinition());
			parserContext
					.registerBeanComponent(new BeanComponentDefinition(
							sessionbuilder.getBeanDefinition(),
							HibernateSourceLocaleBeanDefinitionParser.DEFAULT_HIBERNATE_SESSION_LOCAL));
		}

		if (!parserContext.getRegistry().containsBeanDefinition(
				HibernateSourceLocaleBeanDefinitionParser.DEFAULT_BEAN_NAME)) {// 創建sourcelocale
			BeanDefinitionBuilder builder = BeanDefinitionBuilder
					.genericBeanDefinition(HibernateSourceLocaleBeanDefinitionParser.DEFAULT_BEAN_NAME);
			builder
					.addPropertyReference(
							"source",
							HibernateSourceLocaleBeanDefinitionParser.DEFAULT_HIBERNATE_SESSION_LOCAL);
			parserContext
					.registerBeanComponent(new BeanComponentDefinition(
							builder.getBeanDefinition(),
							HibernateSourceLocaleBeanDefinitionParser.DEFAULT_BEAN_NAME));
		}
	}

	@Deprecated
	private void regisiterJdbcSourceLocale(Element element,
			ParserContext parserContext) {
		String jdbc = element.getAttribute("jdbc");
		if(!"true".equalsIgnoreCase(jdbc)){
			return;
		}
		
		if (!parserContext.getRegistry().containsBeanDefinition(
				JdbcSourceBeanDefinitionParser.DEFAULT_JDBC_SOURCE_BEAN_NAME)) {
			BeanDefinitionBuilder builder = BeanDefinitionBuilder
					.genericBeanDefinition(JdbcSourceBeanDefinitionParser.DEFAULT_JDBC_SOURCE_BEAN_NAME);
			String dataSource = element.getAttribute("dataSource");
			if (!StringUtils.hasText(dataSource)) {
				dataSource = "dataSource";
			}
			builder.addPropertyReference("source", dataSource);
			parserContext
					.registerBeanComponent(new BeanComponentDefinition(
							builder.getBeanDefinition(),
							JdbcSourceBeanDefinitionParser.DEFAULT_JDBC_SOURCE_BEAN_NAME));
		}
	}

	@Deprecated
	private void regisiterDaoProxy(Element element, ParserContext parserContext) {
		Properties daoSources = new Properties();
		String persistentClass =DaoProxyBeanDefinitionParser.DEFAULT_PERSISTENT_CLASS.getName();
		DaoProxyBeanDefinitionParser
				.registerDao(
						parserContext,
						DaoProxyBeanDefinitionParser.DEFAULT_PERSISTENT_CLASS
								.getName(),
						DaoProxyBeanDefinitionParser.DEFAULT_PERSISTENT_CLASS.getName(),
						DaoProxyBeanDefinitionParser.DEFAULT_DAO_SOURCE
								.get(
										DaoProxyBeanDefinitionParser.DEFAULT_PERSISTENT_CLASS)
								.getName());
		
		for (Map.Entry<Class, Class> entry : DaoProxyBeanDefinitionParser.DEFAULT_DAO_SOURCE
				.entrySet()) {
			DaoProxyBeanDefinitionParser.registerDao(parserContext, entry
					.getKey().getName(), entry.getKey().getName(), entry
					.getValue().getName());
			daoSources.setProperty(entry.getKey().getName(), "");
		}

		BeanDefinitionBuilder builder = BeanDefinitionBuilder
		.genericBeanDefinition(DaoProxyBeanDefinitionParser.DEFAULT_DAO_PROXY_BEAN_NAME);
		builder.addPropertyReference("persistentClass", persistentClass);
		builder.addPropertyValue("daoSources", daoSources);
		parserContext.registerBeanComponent(new BeanComponentDefinition(builder
				.getBeanDefinition(), DaoProxyBeanDefinitionParser.DEFAULT_DAO_PROXY_BEAN_NAME));
	}
	
	@Deprecated
	private String regisiterHibernateSessionLocale(Element element, ParserContext parserContext,String hibernateType){
		Class hsclass = HibernateSessionLocaleBeanDefinitionParser.HIBERNATE_BEAN_MAP.get(hibernateType);
		if(hsclass==null){
			hsclass = HibernateSessionLocaleBeanDefinitionParser.DEFAULT_HIBERNATE_SESSION;
		}
		String classname = hsclass.getName();
		if (!parserContext.getRegistry().containsBeanDefinition(classname)) {
			BeanDefinitionBuilder builder = BeanDefinitionBuilder
			.genericBeanDefinition(classname);
			builder.addPropertyReference("sessionFactory", "sessionFactory");
			parserContext.registerBeanComponent(
					new BeanComponentDefinition(builder.getBeanDefinition(),classname));
		}
		return classname;
	}
}
